// handlers/join.rs

use crate::db::Database;
use crate::handlers::DeviceParams;
use crate::handlers::join_accept::{new_device_params, encrypt};
use crate::lorawan::{LoRaWanPacket, parse, convert_to_device_params}; // 引入新的解析函数
use std::sync::Arc;
use tokio::sync::Mutex;

pub async fn handle_join_request(
    packet_data: &[u8], // 修改为接收原始数据包
    db: &Arc<Mutex<Database>>
) -> Result<String, String> {
    // 解析数据包
    let packet = parse(packet_data).map_err(|e| format!("解析失败: {}", e))?;
    // 转换为 DeviceParams
    let params = convert_to_device_params(packet).map_err(|e| format!("转换失败: {}", e))?;

    // 锁定数据库，确保线程安全   
    let db = db.lock().await;  
    // 尝试从数据库获取设备信息
    if let Ok(Some(device)) = db.get_device(&params.dev_eui) {
        // 如果设备已经存在且 AppEUI 匹配，返回错误   
        if device.app_eui == params.app_eui {
            println!("设备 {} 已经存在", params.dev_eui);
            return Err("设备已经存在".to_string());
        } else {
            // 如果设备存在但 AppEUI 不匹配，返回错误
            println!("设备 {} 的 AppEUI 不匹配", params.dev_eui);
            return Err("AppEUI 不匹配".to_string());
        }
    } else {
        // 如果设备不存在，注册新设备
        println!("注册新设备: {}", params.dev_eui);
        // 创建新的设备参数
        let join_accept = new_device_params();
        // 使用 app_key 加密 Join Accept 消息
        let encrypted_join_accept = encrypt(&join_accept, &params.app_key);

        // 创建新的设备参数，包括生成的地址和密钥
        let new_device = DeviceParams {
            dev_eui: params.dev_eui.clone(),
            app_eui: params.app_eui.clone(),
            app_key: params.app_key.clone(),
            dev_nonce: params.dev_nonce.clone(),
            dev_addr: join_accept.dev_addr.clone(),
            nwk_skey: join_accept.nwk_skey.clone(),
            app_skey: join_accept.app_skey.clone(),
            join_nonce: join_accept.join_nonce.clone(),
        };
        // 尝试将新设备添加到数据库
        if let Err(e) = db.add_device(new_device) {
            println!("注册设备失败: {}", e);
            return Err("注册设备失败".to_string());
        } else {
            // 注册成功，返回加密后的 Join Accept 消息
            println!("Join Accept 消息: {}", encrypted_join_accept);
            return Ok(encrypted_join_accept);
        }
    }
}
